package de.puc.defencetower.view.gui;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;

import de.puc.defencetower.controller.iGameController;
import de.puc.defencetower.model.Grass;
import de.puc.defencetower.model.Map;
import de.puc.defencetower.model.MapCell;
import de.puc.defencetower.model.MapElement;
import de.puc.defencetower.model.MapPosition;
import de.puc.defencetower.model.Monster;
import de.puc.defencetower.model.Street;
import de.puc.defencetower.model.Tower;
import de.puc.defencetower.view.gui.GamePanel;

@SuppressWarnings("serial")
public class MapPanel extends GamePanel {

	private static Logger logger = Logger.getLogger("de.puc.defencetower.GameControler");
	private MapPosition lastClicked = null;
	private BufferedImage[] imgTower1;
	private BufferedImage[] imgTower2;
	private BufferedImage[] imgTower3;
	private BufferedImage[] imgGras;
	private BufferedImage[] imgStreet;
	private BufferedImage imgMonster1;
	private BufferedImage imgMonster2;
	private BufferedImage imgMonsterPow;
	private Image img = null;
	
	public final static int PADDING10 = 10; 
	public final static int PADDING15 = 15; 
	public final static int PADDING20 = 20; 

	public MapPanel(Map map, iGameController gameControlerInterface,
			GUIWindow gameWindow) {
		super(map, gameControlerInterface, gameWindow);
		String root = System.getProperty("user.dir");
		String pathGui = root + "/src/de/puc/defencetower/view/gui/res";

		try {
			File pic = null;
			// Tower1
			imgTower1 = new BufferedImage[] {
					ImageIO.read(new File(pathGui + "/tower/turm1a.png")),
					ImageIO.read(new File(pathGui + "/tower/turm1b.png")),
					ImageIO.read(new File(pathGui + "/tower/turm1c.png")),
					ImageIO.read(new File(pathGui + "/tower/turm1d.png")) };

			// Tower2
			imgTower2 = new BufferedImage[] {
					ImageIO.read(new File(pathGui + "/tower/turm2a.png")),
					ImageIO.read(new File(pathGui + "/tower/turm2b.png")),
					ImageIO.read(new File(pathGui + "/tower/turm2c.png")),
					ImageIO.read(new File(pathGui + "/tower/turm2d.png")) };

			// Tower 3
			imgTower3 = new BufferedImage[] {
					ImageIO.read(new File(pathGui + "/tower/turm3a.png")),
					ImageIO.read(new File(pathGui + "/tower/turm3b.png")),
					ImageIO.read(new File(pathGui + "/tower/turm3c.png")),
					ImageIO.read(new File(pathGui + "/tower/turm3d.png")) };

			// Monster
			pic = new File(pathGui + "/monster/monster1.png");
			imgMonster1 = ImageIO.read(pic);

			pic = new File(pathGui + "/monster/monster2.png");
			imgMonster2 = ImageIO.read(pic);

			pic = new File(pathGui + "/monster/schussMonster.png");
			imgMonsterPow = ImageIO.read(pic);

			// Boden
			imgGras = new BufferedImage[] {
					ImageIO.read(new File(pathGui + "/boden/boden1.png")),
					ImageIO.read(new File(pathGui + "/boden/boden2.png")),
					ImageIO.read(new File(pathGui + "/boden/boden3.png")),
					ImageIO.read(new File(pathGui + "/boden/boden4.png")),
					ImageIO.read(new File(pathGui + "/boden/boden5.png")) };

			// Strassen
			imgStreet = new BufferedImage[3];
			imgStreet = new BufferedImage[] {
					ImageIO.read(new File(pathGui + "/strasse/strasse1.png")),
					ImageIO.read(new File(pathGui + "/strasse/strasse2.png")),
					ImageIO.read(new File(pathGui + "/strasse/strasse3.png"))};
		} catch (IOException e) {
			logger.error(e);
		}

	}

	@Override
	protected void paintComponent(Graphics g) {
		if (img == null) {
			img = createVolatileImage(getWidth(), getHeight());
		}

		Graphics newGraphic = img.getGraphics();

		paintMapElements(newGraphic);

		addMouseListener(new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {
			}

			@Override
			public void mousePressed(MouseEvent e) {
				int x = e.getX();
				int y = e.getY();
				MapCell[][] cells = getMap().getCells();

				// im Kartenbereich
				if (x >= 0 && x <= cells[0].length * GUIWindow.CELLSIZE && y >= 0 && y <= cells.length * GUIWindow.CELLSIZE) {
					int xcell = x / GUIWindow.CELLSIZE;
					int ycell = y / GUIWindow.CELLSIZE;

					lastClicked = new MapPosition(xcell, ycell);
				}

			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
			}
		});

		// print Cell Markierung
		if (getLastClicked() != null) {
			MapPosition lc = getLastClicked();
			newGraphic.setColor(Color.white);
			newGraphic.drawRect((lc.getX() * GUIWindow.CELLSIZE) - 1,
					(lc.getY() * GUIWindow.CELLSIZE) - 1,
					GUIWindow.CELLSIZE + 1, GUIWindow.CELLSIZE + 1);
		}

		g.drawImage(img, 0, 0, this);
	}

	private void paintMapElements(Graphics g) {
		MapCell[][] cells = getMap().getCells();
		int ySize = cells.length;
		int xSize = cells[0].length;

		for (int y = 0; y < ySize; y++) {
			for (int x = 0; x < xSize; x++) {
				final MapCell mc;
				mc = cells[y][x];
				int xPos = x * GUIWindow.CELLSIZE;
				int yPos = y * GUIWindow.CELLSIZE;

				for (MapElement mapElement : mc.getMapElements()) {

					if (mapElement instanceof Grass) {
						Grass grass = (Grass) mapElement;
						BufferedImage grassImage;
						switch (grass.getType()) {
						case Grass.GRASS_TYPE0:
							grassImage = imgGras[0];
							break;
						case Grass.GRASS_TYPE1:
							grassImage = imgGras[1];
							break;
						case Grass.GRASS_TYPE2:
							grassImage = imgGras[2];
							break;
						case Grass.GRASS_TYPE3:
							grassImage = imgGras[3];
							break;
						case Grass.GRASS_TYPE4:
							grassImage = imgGras[4];
							break;

						default:
							grassImage = null;
							break;
						}

						g.drawImage(grassImage, xPos, yPos,
								GUIWindow.CELLSIZE, GUIWindow.CELLSIZE, null);
					}
					if (mapElement instanceof Street) {
						Street street = (Street) mapElement;
						BufferedImage streetImage;
						switch (street.getType()) {
						case 0:
							streetImage = imgStreet[0];
							break;
						case 1:
							streetImage = imgStreet[1];
							break;
						case 2:
							streetImage = imgStreet[2];
							break;

						default:
							streetImage = null;
						}

						g.drawImage(streetImage, xPos, yPos,
								GUIWindow.CELLSIZE, GUIWindow.CELLSIZE, null);
					}
					if (mapElement instanceof Monster) {
						Monster m = (Monster) mapElement;

						if (m.isAlive()) {
							switch (m.getType()) {
							case 0:
								g.drawImage(imgMonster1, xPos, yPos,
										GUIWindow.CELLSIZE,
										GUIWindow.CELLSIZE, null);
								break;
							case 1:
								g.drawImage(imgMonster2, xPos, yPos,
										GUIWindow.CELLSIZE,
										GUIWindow.CELLSIZE, null);
								break;

							default:
								break;
							}

							// Live Anzeige
							g.setColor(Color.GREEN);
							g.fillRect(
									xPos + PADDING10,
									yPos,
									(int) ((GUIWindow.CELLSIZE - 2 * PADDING10)
											* m.getHitPoints() / m
											.getMaxHitPoints()), 5);

						} else {
							g.drawImage(imgMonsterPow, xPos, yPos,
									GUIWindow.CELLSIZE, GUIWindow.CELLSIZE,
									null);
						}
					}
					if (mapElement instanceof Tower) {
						Tower t = (Tower) mapElement;
						BufferedImage[] bia = null;

						// Type
						switch (t.getType()) {
						case Tower.TOWERTYPE_SMALL:
							bia = imgTower1;
							break;
						case Tower.TOWERTYPE_MIDDLE:
							bia = imgTower2;
							break;
						case Tower.TOWERTYPE_BIG:
							bia = imgTower3;
							break;
						default:
							break;
						}

						BufferedImage imgTower = null;
						// Level
						switch (t.getLevel()) {
						case 0:
							imgTower = bia[0];
							break;
						case 1:
							imgTower = bia[1];
							break;
						case 2:
							imgTower = bia[2];
							break;
						case 3:
							imgTower = bia[3];
							break;

						default:
							break;
						}

						g.drawImage(imgTower, xPos, yPos, GUIWindow.CELLSIZE,
								GUIWindow.CELLSIZE, null);
						if (t.isShooting()) {
							
							// Type
							switch (t.getType()) {
							case Tower.TOWERTYPE_SMALL:
								g.setColor(Color.RED);
								g.fillOval(xPos + PADDING20, yPos + PADDING20,
										GUIWindow.CELLSIZE - PADDING20*2,
										GUIWindow.CELLSIZE - PADDING20*2);
								break;
							case Tower.TOWERTYPE_MIDDLE:
								g.setColor(Color.BLUE);
								g.fillOval(xPos + PADDING15, yPos + PADDING15,
										GUIWindow.CELLSIZE - PADDING15*2,
										GUIWindow.CELLSIZE - PADDING15*2);
								break;
							case Tower.TOWERTYPE_BIG:
								g.setColor(Color.YELLOW);
								g.fillOval(xPos + PADDING10, yPos + PADDING10,
										GUIWindow.CELLSIZE - PADDING10*2,
										GUIWindow.CELLSIZE - PADDING10*2);
								break;
							default:
								break;
							}
						}
					}
				}

			}
		}
	}

	public void refresh() {
		paint(getGraphics());
	}

	public MapPosition getLastClicked() {
		return lastClicked;
	}
}
